

pub trait BodyDecode<'de> {
    fn decode(buf_ref: &mut &'de [u8]) -> Option<Self>
    where
        Self: Sized;
}

impl<'de> BodyDecode<'de> for u8 {
    fn decode(buf_ref: &mut &[u8]) -> Option<Self>
    where
        Self: Sized,
    {
        let buf = *buf_ref;
        let len = buf.len();
        if len < 1 {
            None
        } else {
            let v = unsafe { *buf.get_unchecked(0) };
            *buf_ref = &buf[1..];
            Some(v)
        }
    }
}

impl<'de> BodyDecode<'de> for u16 {
    fn decode(buf_ref: &mut &[u8]) -> Option<Self>
    where
        Self: Sized,
    {
        let buf = *buf_ref;
        let len = buf.len();
        if len < 2 {
            None
        } else {
            let v =
                unsafe { ((*buf.get_unchecked(0) as u16) << 8) | (*buf.get_unchecked(1) as u16) };
            *buf_ref = &buf[2..];
            Some(v)
        }
    }
}

impl<'de> BodyDecode<'de> for i16 {
    fn decode(buf_ref: &mut &[u8]) -> Option<Self>
    where
        Self: Sized,
    {
        let buf = *buf_ref;
        let len = buf.len();
        if len < 2 {
            None
        } else {
            let v =
                unsafe { ((*buf.get_unchecked(0) as i16) << 8) | (*buf.get_unchecked(1) as i16) };
            *buf_ref = &buf[2..];
            Some(v)
        }
    }
}


impl<'de> BodyDecode<'de> for u32 {
    fn decode(buf_ref: &mut &[u8]) -> Option<Self>
    where
        Self: Sized,
    {
        let buf = *buf_ref;
        let len = buf.len();
        if len < 4 {
            None
        } else {
            let v = unsafe {
                ((*buf.get_unchecked(0) as u32) << 24)
                    | ((*buf.get_unchecked(1) as u32) << 16)
                    | ((*buf.get_unchecked(2) as u32) << 8)
                    | (*buf.get_unchecked(3) as u32)
            };
            *buf_ref = &buf[4..];
            Some(v)
        }
    }
}

impl<'a, 'de: 'a> BodyDecode<'de> for &'a [u8] {
    fn decode(buf_ref: &mut &'de [u8]) -> Option<Self>
    where
        Self: Sized,
    {
        let buf = *buf_ref;
        let len = buf.len();
        if len < 1 {
            None
        } else {
            let body_len = unsafe { *buf.get_unchecked(0) as usize };
            if len < (1 + body_len) {
                None
            } else {
                let body = &buf[1..(1 + body_len)];
                *buf_ref = &buf[(1 + body_len)..];
                Some(body)
            }
        }
    }
}
